package com.swing;

import com.swing.panel.BgPanel;
import com.swing.panel.GamePanel;
import com.swing.panel.UIPanel;

import javax.swing.*;
import java.awt.*;

/**
 * 游戏窗口类，用于创建和管理Swing应用程序的主窗口
 * 封装了JFrame的初始化和基本设置，简化游戏窗口的创建流程
 */
public class GameWindow {

    // 窗口标题
    private String title;
    // 窗口宽度（像素）
    private int width;
    // 窗口高度（像素）
    private int height;
    // 底层使用的Swing窗口对象
    private JFrame frame;
    // 游戏面板
    private BgPanel bgPanel;
    private GamePanel gamePanel;
    private UIPanel uiPanel;

    /**
     * 构造方法，初始化游戏窗口的基本属性
     *
     * @param title  窗口标题文字
     * @param width  窗口宽度（像素）
     * @param height 窗口高度（像素）
     */
    public GameWindow(String title, int width, int height) {
        // 保存窗口标题、宽度和高度到成员变量
        this.title = title;
        this.width = width;
        this.height = height;

        // 初始化主窗口JFrame
        frame = new JFrame(title);
        // 设置窗口关闭操作：关闭窗口时退出程序
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // 创建层级面板JLayeredPane，用于管理不同层级的面板
        // 层级面板允许组件按层级叠加显示，解决元素遮挡问题
        JLayeredPane layeredPane = new JLayeredPane();
        // 设置层级面板的首选大小为窗口大小
        layeredPane.setPreferredSize(new Dimension(width, height));

        // 1. 添加背景层（最底层）
        bgPanel = new BgPanel();
        // 设置背景面板大小与窗口一致，位置从左上角(0,0)开始
        bgPanel.setBounds(0, 0, width, height);
        // 将背景面板添加到层级面板的默认层（最低层级）
        layeredPane.add(bgPanel, JLayeredPane.DEFAULT_LAYER);

        // 2. 添加游戏元素层（中间层）
        gamePanel = new GamePanel();
        // 设置游戏面板大小与窗口一致，覆盖在背景层之上
        gamePanel.setBounds(0, 0, width, height);
        // 将游戏面板添加到调色板层（层级高于默认层）
        layeredPane.add(gamePanel, JLayeredPane.PALETTE_LAYER);

        // 3. 添加UI层（最顶层）
        uiPanel = new UIPanel();
        // 设置UI面板大小与窗口一致，覆盖在所有层之上
        uiPanel.setBounds(0, 0, width, height);
        // 将UI面板添加到模态层（层级高于调色板层，确保UI控件优先显示）
        layeredPane.add(uiPanel, JLayeredPane.MODAL_LAYER);

        // 将层级面板添加到主窗口
        frame.add(layeredPane);
        // 调整窗口大小以适应层级面板的首选大小
        frame.pack();

        // 设置窗口在屏幕中居中显示
        frame.setLocationRelativeTo(null);
    }

    /**
     * 显示窗口的方法
     * 调用后窗口将在屏幕上可见，并确保游戏面板获得焦点以响应键盘事件
     */
    public void show() {
        // 设置主窗口为可见状态
        // 使窗口及其包含的所有组件在屏幕上显示出来
        frame.setVisible(true);

        // 设置游戏面板为可获取焦点状态
        // 允许游戏面板接收键盘输入事件（前提是获得焦点）
        gamePanel.setFocusable(true);

        // 使用SwingUtilities.invokeLater()确保在事件调度线程中执行焦点请求
        // 避免多线程环境下可能出现的UI操作冲突
        SwingUtilities.invokeLater(() -> {
            // 请求游戏面板在窗口中获取焦点
            // 确保键盘事件能被游戏面板接收和处理（而非其他组件）
            gamePanel.requestFocusInWindow();
        });
    }

    public void update(float deltaTime) {
        gamePanel.update(deltaTime);
    }

    public void render() {
        gamePanel.render();
    }
}